/*
 *  Copyright (C) 2011 Rémi Thebault
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/>.
 */


#include <QPrinterInfo>
#include <QDir>
#include <QPainter>

#include "procycle.h"
#include "tasktreeview.h"
#include "tasktreemodel.h"
#include "ganttscene.h"
#include "printdialog.h"
#include "ui_printdialog.h"


void fillPaperSizes(QComboBox *box, QString printerName);
void fillAllPaperSizes(QComboBox *box);
QString paperSizeToString(QPrinter::PaperSize ps);
QPrinter::PaperSize stringToPaperSize(QString s);
void selectA4(QComboBox *box);


void PrintDialog::handlePrintRequest(ProCycle *app) {
    QPrinter printer;
    PrintScene printScene (0, app, &printer);
    PrintDialog dlg (app, &printer, &printScene);
    if (dlg.exec()) {
        printer.setOutputFormat(QPrinter::PdfFormat);
        printer.setOutputFileName(QDir::home().filePath("print.pdf"));
        QPainter painter(&printer);
        printScene.render(&painter);
    }
}


PrintDialog::PrintDialog(ProCycle *app, QPrinter *printer, PrintScene *printScene) :
    QDialog(app),
    PCChild(app),
    ui(new Ui::PrintDialog),
    m_printer(printer),
    m_printScene(printScene)
{
    ui->setupUi(this);
    ui->preview->setBackgroundRole(QPalette::Window);

    QList<QPrinterInfo> pis = QPrinterInfo::availablePrinters();
    foreach (QPrinterInfo pi, pis) {
        ui->printerList->addItem(pi.printerName());
    }
    QPrinterInfo def = QPrinterInfo::defaultPrinter();
    if (!def.isNull()) {
        ui->printerList->setCurrentIndex(ui->printerList->findText(def.printerName()));
        fillPaperSizes(ui->paperList, def.printerName());
    }

    ui->preview->setScene(m_printScene);
    ui->preview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->preview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    float ratTarget = ui->preview->height() / ui->preview->width();
    float ratSource = m_printScene->sceneRect().height() / m_printScene->sceneRect().width();

    if (ratTarget > ratSource) {
        float scale = ui->preview->width() / m_printScene->sceneRect().width();
        ui->preview->scale(scale, scale);
    }
    else {
        float scale = ui->preview->height() / m_printScene->sceneRect().height();
        ui->preview->scale(scale, scale);
    }
}


PrintDialog::~PrintDialog()
{
    delete ui;
}



void PrintDialog::printerTypeChanged() {
    ui->printerList->setEnabled(ui->printRad->isChecked());
    if (ui->printRad->isChecked()) {
        m_printer->setOutputFormat(QPrinter::NativeFormat);
        fillPaperSizes(ui->paperList, ui->printerList->currentText());
    }
    else if (ui->pdfRad->isChecked()) {
        m_printer->setOutputFormat(QPrinter::PdfFormat);
        fillAllPaperSizes(ui->paperList);
    }
    else if (ui->psRad->isChecked()) {
        m_printer->setOutputFormat(QPrinter::PostScriptFormat);
        fillAllPaperSizes(ui->paperList);
    }
}

void PrintDialog::printerChanged() {
    QString printerName = ui->printerList->currentText();
    m_printer->setPrinterName(printerName);
    fillPaperSizes(ui->paperList, printerName);
}

void PrintDialog::rangeChanged() {
    if (ui->printAllRad->isChecked()) {
        m_printer->setPrintRange(QPrinter::AllPages);
    }
    else if (ui->pagesRad->isChecked()) {
        m_printer->setPrintRange(QPrinter::PageRange);
        m_printer->setFromTo(ui->fromSpn->value(), ui->toSpn->value());
    }
}

void PrintDialog::layoutChanged() {
    if (ui->landscapeRad->isChecked()) {
        m_printer->setOrientation(QPrinter::Landscape);
    }
    else if (ui->portraitRad->isChecked()) {
        m_printer->setOrientation(QPrinter::Portrait);
    }
    if (!ui->paperList->currentText().isEmpty()) {
        m_printer->setPaperSize(stringToPaperSize(ui->paperList->currentText()));
    }
}


void PrintDialog::optionChanged() {
    ui->preview->update();
}


void fillAllPaperSizes(QComboBox* box) {
    box->clear();
    box->addItem("A0");
    box->addItem("A1");
    box->addItem("A2");
    box->addItem("A3");
    box->addItem("A4");
    box->addItem("A5");
    box->addItem("A6");
    box->addItem("A7");
    box->addItem("A8");
    box->addItem("A9");
    box->addItem("B0");
    box->addItem("B1");
    box->addItem("B2");
    box->addItem("B3");
    box->addItem("B4");
    box->addItem("B5");
    box->addItem("B6");
    box->addItem("B7");
    box->addItem("B8");
    box->addItem("B9");
    box->addItem("B10");
    box->addItem("C5E");
    box->addItem("Comm10E");
    box->addItem("DLE");
    box->addItem("Executive");
    box->addItem("Folio");
    box->addItem("Ledger");
    box->addItem("Legal");
    box->addItem("Letter");
    box->addItem("Tabloid");
    box->addItem("Custom");
    selectA4(box);
}


void fillPaperSizes(QComboBox *box, QString printerName) {
    QList<QPrinterInfo> pis = QPrinterInfo::availablePrinters();
    if (pis.count() > 0) {
        box->clear();
        foreach (QPrinterInfo pi, pis) {
            if (pi.printerName() == printerName) {
                QList<QPrinter::PaperSize> pss = pi.supportedPaperSizes();
                if (pss.count() > 0) {
                    foreach (QPrinter::PaperSize ps, pss) {
                        QString str = paperSizeToString(ps);
                        if (box->findText(str) == -1) box->addItem(paperSizeToString(ps));
                    }
                    selectA4(box);
                }
                else {
                    fillAllPaperSizes(box);
                }
            }
        }
    }
    else {
        fillAllPaperSizes(box);
    }
}


void selectA4(QComboBox *box) {
    int i = box->findText("A4");
    if (i != -1) {
        box->setCurrentIndex(i);
    }
}

QString paperSizeToString(QPrinter::PaperSize ps) {
    switch (ps) {
        case QPrinter::A0: return "A0";
        case QPrinter::A1: return "A1";
        case QPrinter::A2: return "A2";
        case QPrinter::A3: return "A3";
        case QPrinter::A4: return "A4";
        case QPrinter::A5: return "A5";
        case QPrinter::A6: return "A6";
        case QPrinter::A7: return "A7";
        case QPrinter::A8: return "A8";
        case QPrinter::A9: return "A9";
        case QPrinter::B0: return "B0";
        case QPrinter::B1: return "B1";
        case QPrinter::B2: return "B2";
        case QPrinter::B3: return "B3";
        case QPrinter::B4: return "B4";
        case QPrinter::B5: return "B5";
        case QPrinter::B6: return "B6";
        case QPrinter::B7: return "B7";
        case QPrinter::B8: return "B8";
        case QPrinter::B9: return "B9";
        case QPrinter::B10: return "B10";
        case QPrinter::C5E: return "C5E";
        case QPrinter::Comm10E: return "Comm10E";
        case QPrinter::DLE: return "DLE";
        case QPrinter::Executive: return "Executive";
        case QPrinter::Folio: return "Folio";
        case QPrinter::Ledger: return "Ledger";
        case QPrinter::Legal: return "Legal";
        case QPrinter::Letter: return "Letter";
        case QPrinter::Tabloid: return "Tabloid";
        case QPrinter::Custom: return "Custom";
        default: break;
    }
    return "Custom";
}



QPrinter::PaperSize stringToPaperSize(QString s) {
    if (s.count() < 2) {
        return QPrinter::Custom;
    }
    char c1, c2;
    c1 = s.at(0).toAscii();
    if (c1 == 'A') {
        c2 = s.at(1).toAscii();
        switch (c2) {
            case '0': return QPrinter::A0;
            case '1': return QPrinter::A1;
            case '2': return QPrinter::A2;
            case '3': return QPrinter::A3;
            case '4': return QPrinter::A4;
            case '5': return QPrinter::A5;
            case '6': return QPrinter::A6;
            case '7': return QPrinter::A7;
            case '8': return QPrinter::A8;
            case '9': return QPrinter::A9;
        }
    }
    else if (c1 == 'B') {
        c2 = s.at(1).toAscii();
        switch (c2) {
            case '0': return QPrinter::B0;
            case '1': {
                if (s == "B10") {
                    return QPrinter::B10;
                }
                return QPrinter::B1;
            }
            case '2': return QPrinter::B2;
            case '3': return QPrinter::B3;
            case '4': return QPrinter::B4;
            case '5': return QPrinter::B5;
            case '6': return QPrinter::B6;
            case '7': return QPrinter::B7;
            case '8': return QPrinter::B8;
            case '9': return QPrinter::B9;
        }
    }
    else {
        if (s == "C5E") {
            return QPrinter::C5E;
        }
        else if (s == "Comm10E") {
            return QPrinter::Comm10E;
        }
        else if (s == "DLE") {
            return QPrinter::DLE;
        }
        else if (s == "Executive") {
            return QPrinter::Executive;
        }
        else if (s == "Folio") {
            return QPrinter::Folio;
        }
        else if (s == "Ledger") {
            return QPrinter::Ledger;
        }
        else if (s == "Legal") {
            return QPrinter::Legal;
        }
        else if (s == "Letter") {
            return QPrinter::Letter;
        }
        else if (s == "Tabloid") {
            return QPrinter::Tabloid;
        }
        else if (s == "Custom") {
            return QPrinter::Custom;
        }
    }
    return QPrinter::Custom;
}



PrintScene::PrintScene(QObject *parent, ProCycle *app, QPrinter *printer) :
    QGraphicsScene(printer->paperRect(), parent),
    m_printer(printer)
{

    m_treeWidth = printer->pageRect().width() / 4;


    m_treeView = new TaskTreeView(app, 0);
    m_treeView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_treeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_treeView->setFixedWidth(m_treeWidth);
    m_treeView->setFixedHeight(printer->pageRect().height());
    m_treeView->setModel(app->taskTreeModel());
    m_treeView->header()->moveSection(1, 0);
    m_treeView->syncExpansion();
    m_ganttScene = new GanttScene(app,
                                  QRectF(0, 0,
                                         printer->pageRect().width() - m_treeWidth,
                                         printer->pageRect().height()),
                                  this);
}



PrintScene::~PrintScene() {
    delete m_treeView;
}

void PrintScene::drawForeground(QPainter *painter, const QRectF &rect) {
    m_treeView->render(painter, m_printer->pageRect().topLeft());
    m_ganttScene->render(painter, QRectF(m_printer->pageRect().x() + m_treeWidth,
                                         m_printer->pageRect().top(),
                                         m_printer->pageRect().width() - m_treeWidth,
                                         m_printer->pageRect().height()));
}

